//: Playground - noun: a place where people can play

import UIKit

// 存储属性 -- 定义

// 定义一个结构体如下，FixedLengthRange代表一个创建后无法改变的区间
struct FixedLengthRange {

    var firstValue: Int
    let length:Int
}

var rangeOfThreeItens = FixedLengthRange(firstValue: 0, length: 3);

// rangeOfThreeItens 实例包括了名为firstValue的变量存储属性和length的常量存储属性
// 其中length在创建后无法修改
rangeOfThreeItens.firstValue = 7;

// 结构体是值类型，当值类型的实例呗声明为常量的时候，他的所有属性都变成了常量
let rangeOfThreeItens1 = FixedLengthRange(firstValue: 0, length: 3);


// 延迟存储属性
// swift在属性前加lazy关键字来标记一个延迟存储属性，延迟存储属性必须用变量（var）

class DataImporter {

    var fileName = "data.text"
    /** 导入数据**/
}

// DataManager 用来管理和提供对这个字符串数组的访问

class DataManager {

    lazy var importer = DataImporter()
    var data = [String]()

    /**管理数据**/
}

let manager = DataManager()

manager.data.append("someData")

// DataImporter不需要立刻创建，只有在使用的时候才去创建。如下代码
print(manager.importer.fileName);


// 计算属性

// 计算属性不直接存储值，而是提供一个getter和一个可选的setter来间接获取、设置其他属性和变量的值

struct Point {

    var x = 0.0, y = 0.0
}

struct Size {

    var width = 0.0, height = 0.0
}

struct Rect {

    var origin = Point()
    var size = Size()
    var center: Point {
    
        get {
        
            let centerX = origin.x + size.width * 0.5
            let centerY = origin.y + size.height * 0.5
            return Point(x: centerX, y: centerY)
        }
        
        set (newCenter){
            
            origin.x = newCenter.x - size.width * 0.5
            origin.y = newCenter.y - size.height * 0.5
            
            // 没有设置newCenter  可以用newValue
        }
    }
}

// 创建一个矩形

var square = Rect(origin: Point(x: 0.0, y: 0.0), size: Size(width: 10.0, height: 10.0))

// 重新设置矩形的中心点
let initialSquareCenter = square.center
square.center = Point(x: 20.0, y: 20.0);

// 只读计算属性
/* 
只有getter没有setter的计算属性
只读计算属性总是返回一个值，可以通过点语法访问，但是不能设置
只读计算属性可以省略get和花括号
*/

struct Cuboid {

    var width = 0.0, height = 0.0, depth = 0.0
    
    var volume: Double {
    
        return width * height * depth
    }
}

// 属性观察器

/*
 属性观察器监控和响应属性值的变化，每次属性被设置值的时候都会调用。
 延迟属性不可以设置属性观察器
 可以通过重写属性的方式为继承的属性添加观察器
 */

class StepCounter {

    var totalStep: Int = 0 {
    
        willSet {
            
            print("现在总步数是\(newValue)步")
        }
        
        didSet {
        
            if totalStep > oldValue {
                
                print("增加了\(totalStep - oldValue)步")
            }
        }
    }
    
}

let setpCounter = StepCounter()
setpCounter.totalStep = 200
setpCounter.totalStep = 500

// 类型属性

/*
 必须给存储型类型属性，指定一个默认值，因为类型本身，无法在初始化过程中，使用构造器给类型属性赋值、
 存储型类型属性是延迟初始化的，并且不要加lazy,多线程同时访问也只会初始化一次。
 在Swift中，类型属性是类型定义的一部分，写在类型最外层花括号内，作用域就是在该类型支持的范围内。
 用关键字static来定义类型属性
 在类中，用关键字class来支持子类对父类的实现进行重写。
 */

// 只写了只读计算型类型属性
struct MyStruct{
    
    static var storedTypeProperty = "Some Value"
    
    static var comutedTypeProperty : Int{
        return 998
    }
}

enum MyEnum{
    static var storedTypeProperty = "Some Value"
    
    static var comutedTypeProperty : Int{
        return 998
    }
    
}
class MyClass {
    static var storedTypeProperty = "Some Value"
    
    static var comutedTypeProperty : Int{
        return 998
    }
    class var overridedableComutedTypeProperty : Int{
        return 100
    }
}

// 跟实例的属性一样，类型属性可以用点语法来访问，只是不需要通过实例。
MyEnum.storedTypeProperty = "6666"


		